home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 November
/
EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso
/
earcd
/
util
/
text
/
frexxedv.lha
/
FrexxEdpatch
/
fpl
/
wordpro.FPL
< prev
next >
Wrap
Text File
|
1995-09-22
|
15KB
|
484 lines
/*
* WHAT IS THIS?
*
* WordPro.FPL is perhaps the most advanced FPL program written for FrexxEd
* at this time. It brings interactive word-processor-style word wrap
* functionality to the editor.
*
* "word-processor-style" means that
* A. All word wrapping is "paragraph" oriented. All lines within the same
* paragraph are separated with 'soft' newlines (that is a "\x01\n" in my
* program!),
* B. If a line is longer than the right margin is set to, the words that are
* "off the edge" are moved down to the line below and a 'soft' newline is
* added to the end of the line. If the line below gets too long by the
* operation, it performs the same with that line...
* C. If the first word of the line below would fit at the end of the current,
* it is moved up. (And then the same check is done on the line below.)
*/
/*
* Current restrictions:
* o Pretty slow on large paragraphs, perhaps I'll make a limit in amount
* of lines that can get 'fixed' on each invoke.
* o If the first word of a line fits on the line above is only checked for
* if the current line is out of right margin ( and '_fitprev' is on ).
* o If the first word of the line below fits on the current line is only
* checked for when deleting.
* o There is no kind of left margin indentation support
*/
/*
* WordProWrap()
*
* Checks the current line to see if it is longer than the margin allows.
* If it is, it performs actions to word wrap it properly
*/
export int WordProWrap(void)
{
string word;
int sbyte = ReadInfo("byte_position");
int line = ReadInfo("line");
int sline=line;
int cursorline = line;
int jumpback;
int wrapped;
int len = ReadInfo("line_length");
int visible = Visible(0);
const int wall = ReadInfo("wall_right");
if(wall >= len)
return 1;
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")+1);
do {
int steps;
int backsteps;
len = ReadInfo("line_length");
if(IsLineWordWrapped(line)) {
wrapped=1; /* it is wrapped! */
len--; /* don't count the cookie! */
}
else
wrapped=0;
if(wall >= len)
break;
// Request(sprintf("line %d is %d bytes long", line, len));
jumpback=1;
if(line == cursorline) {
/* the cursor-line */
if(ReadInfo("column") + (len-sbyte) >= wall) {
/* we reached the edge when appending text to the left side
of text that is about to get wrapped! */
backsteps= len-sbyte; /* this number of steps from the current
right edge */
jumpback=0;
}
if(ReadInfo("WordPro_fitprev")) {
/*
* This checks if the first word on the line fits on the uppper line
*/
while (IsLineWordWrapped(line-1)) {
int uplen;
GotoLine(line-1);
uplen = ReadInfo("line_length");
word = GetWord(line, 0);
if(sbyte > strlen(word) &&
uplen + strlen(word)+2 < wall) {
GotoLine(--line, len);
Backspace();
Delete();
Output(" ");
sbyte += uplen;
sline--;
//Request("We merged the line with the upper one!");
}
else {
GotoLine(line);
break;
}
}
}
/* ----- */
cursorline=-1; /* never ever do this again */
}
GotoLine(line, ReadInfo("line_length")); /* jump to end of line! */
do {
steps+=CursorLeftWord();
} while (line==ReadInfo("line") &&
ReadInfo("column")>1 &&
wall<ReadInfo("column"));
if(!jumpback && (steps < backsteps)) {
/* then this is a false backstepper! */
jumpback=1;
}
if (line==ReadInfo("line") && ReadInfo("column")>1) {
int byte = ReadInfo("byte_position");
while(GetChar(--byte) != ' ') {
steps++;
CursorLeft();
if(!byte) {
GotoLine(line,wall);
Output("\x01\n");
break 2;
}
}
byte++;
while(GetChar(--byte) == ' ')
Backspace();
Output("\x01\n");
}
/*
if(wall <= ReadInfo("column")) {
Output("\x01\n");
}
*/
line++; /* we've come down one line by now! */
if(!jumpback) {
jumpback=1;
sbyte = steps-backsteps;
sline = line;
}
if(wrapped) {
//Request("This is a wrapped line, check if next word fits here!");
len = ReadInfo("line_length");
word = GetWord(line+1, 0); /* get first word on next line */
if(strlen(word)+len < wall) {
/* we think next word is gonna fit on our line! */
GotoLine(line, len); /* jump to end of line! */
Backspace(); /* get rid of our 0x01 code! */
Delete(); /* Merge next line to our! */
if(GetChar()!=' ')
Output(" "); /* make us a space! */
}
else {
//Request("Nope! It doesn't...");
if(len < wall)
wrapped=0;
}
}
else {
//Request(sprintf("line %d lines %d", line, ReadInfo("lines")));
if(line < ReadInfo("lines") && !IsLineWordWrapped(line)) {
//Request("boo");
sbyte++;
}
}
} while(wrapped); /* continue until done! */
if(jumpback) {
GotoLine(sline, sbyte); /* jump to start-pos! */
if(GetCursor(sbyte, sline) < sbyte) {
GotoLine(sline+1);
}
}
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")-1);
Visible(visible);
}
/*
* WordProDelete0x01()
*
* Called before each invoke of Delete() to make a deletion of the 'soft'
* newline character (ASCII 0x01) make a deletion of the following
* newline too, and a decent word wrap if the line gets too long!
*/
int newlinedelete;
export int WordProDelete0x01(int number)
{
if(1 == GetChar()) { /* are we standing on a 0x01 character? */
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")+1);
if(number>1) /* specified number? */
number--;
Delete(number+2); /* delete the 0x01 and newline too then! */
WordProWrap(); /* wrap this long line! */
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")-1);
return 1; /* quit the actual Delete() */
}
}
/*
* WordProDelete0x01()
*
* Called after each invoke of Delete() to make a decent word wrap if the
* line gets short enough to fit the first word on the line below!
*/
export int WordProDelete(void)
{
int line=ReadInfo("line");
if(IsLineWordWrapped(line)) {
int len;
int sline=line;
int sbyte=ReadInfo("byte_position");
int visible=Visible(0);
string word;
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")+1);
while(line <= ReadInfo("lines")) {
word = GetWord(line+1, 0); /* get first word on next line */
len = ReadInfo("line_length") + strlen(word)+1; /* a space too! */
if(ReadInfo("wall_right") >= len) {
GotoLine(line++, len);
Backspace(); /* remove magic cookie! */
Delete(); /* remove newline */
Output(" ");
WordProWrap(); /* do the dance! */
}
else
break;
}
GotoLine(sline, sbyte); /* jump to start-pos! */
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")-1);
Visible(visible);
}
}
/*
* WordProSave()
*
* Called before the actual save is done. If the user confirms the question,
* it replaces all soft newlines to spaces and then saves it like that.
*/
int oursavehook;
export int WordProSave(string file, string pack)
{
int new;
int savemode = ReadInfo("wordpro_save");
if(3 == savemode) {
savemode = Request("How do you want it saved?", "Save option",
"Raw|Softs too|Only hards|Cancel");
if(!savemode--) {
return 1;
}
}
if(!oursavehook && savemode) {
int us = GetEntryID();
new = New();
oursavehook=1; /* prevent us from getting recursive! */
if(new) {
string filename;
string replacedsoft;
CurrentBuffer(new); /* jump to the new one */
BlockPaste(us); /* paste the original buffer in the new */
GotoLine(1); /* go to the top! */
if(savemode==2) {
/* this is "only hard" newlines should be left, replace all softies
with a single space! */
replacedsoft = " ";
}
else {
/* Keep the soft newlines as newlines in the output! */
replacedsoft = "\n";
}
Replace(1, "\x01\n", replacedsoft, "f+"); /* replace all soft newlines */
filename = ReadInfo("full_file_name", us); /* get file name */
if(strlen(file))
/* done like this to still support Save() with a given name */
filename=file;
Save(filename, pack); /* save the new buffer to the original file */
CurrentBuffer(us); /* jump back to the orignal buffer */
/*
* Now, write the date and time of our "faked" save into the
* info variable for our good old buffer to maintain the proper
* data! (and most of all, to avoid that nasty 'FileChanged'
* exception when trying to save a file that is older than the file
* actually is on disk!)
*/
SetInfo(us, "ds_Days", ReadInfo("ds_Days", new));
SetInfo(us, "ds_Minute", ReadInfo("ds_Minute", new));
SetInfo(us, "ds_Tick", ReadInfo("ds_Tick", new));
SetInfo(us, "changes", 0); /* clear the changes flag! */
Kill(new); /* kill our temporary buffer */
}
oursavehook=0; /* allow us to get started once again! */
}
return new; /* if non-zero, the "real" save is stopped */
}
/*
* WordProOpenAndWrap()
*
* This function takes the specified file, or if none is specified, prompts
* for one, loads it into a new buffer and word wraps it according to
* its knowledge.
*/
int export WordProOpenAndWrap(string file)
{
int new;
if(!strlen(file)) {
file=PromptFile();
if(!strlen(file))
/* cancel or error occured! */
return 1;
}
new = New();
if(new) {
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")+1); /* prevent recurse */
CurrentBuffer(new); /* jump to new buffer */
Load(file); /* load the specified file */
WordProWrapLines(1, ReadInfo("lines")); /* do the entire buffer! */
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")-1); /* allow recurse */
SetInfo(-1, "wordpro", 1); /* 'wordpro' is enabled for this buffer! */
}
else
return 1;
}
int export WordProWrapBuffer()
{
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")+1); /* prevent recurse */
WordProWrapLines(1, ReadInfo("lines")); /* do the entire buffer! */
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")-1); /* allow recurse */
}
int export WordProWrapBlock()
{
if(ReadInfo("block_exist")) {
BlockMark(0);
WordProWrapLines(ReadInfo("block_begin_y"), ReadInfo("block_end_y"));
}
else
ReturnStatus("No block marked!");
}
int export WordProWrapLines(int firstline, int lastline)
{
int line;
int numlines;
int len;
int count;
SetInfo(-1, "wordpro", 1); /* we wanna run wordpro dammit! ;) */
/* Do the tango!
*
* Combine all 'paragraphs' with soft newlines!
*/
numlines = ReadInfo("lines"); /* read number of lines */
for(line= firstline; line < lastline; line++) { /* the last line can't be soft! */
len = GetByte(999999, line); /* get byte position */
if(len > ReadInfo("wall_right")/2 &&
!IsLineWordWrapped(line)) {
/* the text of this line reaches longer than half the width */
/* and it isn't previously wrapped (like if the file was saved 'raw'
in a previous WordPro editing session)! */
GotoLine(line, len); /* goto end of line */
/* The expression just above does not fully function in FrexxEd 1.7
and earlier if the length of the line is longer than the width
of the screen/window... */
if(!Isspace(GetChar(0, line+1))) {
/* The paragraph seems to continue on the following line,
since the first column of that line isn't white space! */
Output("\x01");
}
}
/* next one please! */
}
/*
* Now, let's scan all lines and wrap them to a decent level!
*/
for(line= firstline; line <= lastline;) {
GotoLine(line); /* jump to the line in question! */
WordProWrap(); /* do the secret wrap trick! */
count = ReadInfo("lines")-numlines; /* this amount of new lines! */
numlines += count; /* we're at this amount now! */
lastline += count; /* add to this one too! */
if(count)
line += count; /* skip those new ones since they're already wrapped! */
else
line++;
}
SetInfo(-1, "_wordpro", ReadInfo("_wordpro")-1); /* allow yet again! */
}
export void WordProPrefs()
{
PromptInfo(-1, "WordPro Preferences", -1, -1,
"wordpro", "wall_right", "wordpro_save", "wordpro_fitprev",
"wordpro_open");
}
int IsLineWordWrapped(int line)
{
if(line>0) {
int len= GetByte(999999, line);
if(len>1 && (1 == GetChar(len-1, line))) {
return 1;
}
}
return 0;
}
ReadInfo("_wordpro");
if(GetErrNo()) { /* just a way to make the menu only once, even if this file
is executed repeatedly! */
/*
* Create our menu setup:
*/
MenuAdd("t", "WordPro");
MenuAdd("i", "Open...", "WordProOpenAndWrap(\"\");", "control w o");
MenuAdd("i", "Wrap Block", "WordProWrapBlock();", "control w b");
MenuAdd("i", "Save...", "Save();", "control w s");
MenuAdd("i", "Prefs", "WordProPrefs();");
MenuBuild();
}
/*
* This little beast is here only to prevent recursion where we don't want
* it...
*/
ConstructInfo("_wordpro", "", "", "ILH", "", 0, 999, 0);
/*
* This is the general right-edge setting.
*/
ConstructInfo("wall_right", "", "", "WIL(display)", "", 0, 999, 79);
/*
* Toggle this mode on/off with this!
*/
ConstructInfo("wordpro", "", "", "WBL(system)", "", 0, 0);
/*
* Control how the saving is performed with this.
*/
ConstructInfo("wordpro_save", "", "", "WCG(system)", "Raw|Softs too|Only Hards|Query", 0, 0, 2);
/*
* Make all the regular loads word wrap the file!
*/
ConstructInfo("wordpro_open", "", "", "WBG(system)", "", 0, 0, 0);
/*
* This variable enables the wordpro script to check if the first word of
* the line fits on the line above.
*/
ConstructInfo("wordpro_fitprev", "", "", "WBG(system)", "", 0, 0, 1);
FACT(0x01, 'S', "^", ' '); /* non-visible character! */
AddMode(0,"wordpro", "",""); // Add as minor mode!
/*
* All this can only be accomplished by some pretty extensive hooking...
*/
HookPast("Output", "WordProWrap();", "wordpro&!_wordpro");
HookPast("BlockPaste", "WordProWrap();", "wordpro&!_wordpro");
HookPast("Delete", "WordProDelete();", "wordpro&!_wordpro");
HookPast("Backspace", "WordProDelete();", "wordpro&!_wordpro");
HookPast("DeleteWord", "WordProDelete();", "wordpro&!_wordpro");
HookPast("BackspaceWord", "WordProDelete();", "wordpro&!_wordpro");
Hook("Save", "WordProSave", "wordpro");
Hook("Delete", "WordProDelete0x01", "wordpro&!_wordpro");
Hook("GotFile", "WordProWrapBuffer();", "wordpro_open&!_wordpro");